%header{
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <vector>
#include "expression.h"
#include "numericExpression.h"
#include "primaryExpression.h"
#include "numericBinaryOperation.h"
#include "numericUnaryOperation.h"
#include "numericPrimaryExpression.h"
#include "intPrimaryExpression.h"
#include "columnReference.h"
#include "booleanExpression.h"
#include "logicBinaryOperation.h"
#include "logicUnaryOperation.h"
#include "truthValue.h"
#include "column.h"
#include "columnlist.h"
#include "tablecolumn.h"
#include "tablecolumnlist.h"
#include "tableconstraint.h"
#include "tableconstraintlist.h"
#include "enums.h"
#include "table.h"
#include "view.h"
#include "schema.h"
#include "select.h"
#include "from.h"
#include "fromcomponent.h"
#include "where.h"
#include "querytree.h"
#include "simplequery.h"
#include "formulagenerator.h"
#include "schemacomponentformula.h"
#include "existsExpression.h"
#include "groupBy.h"
#include "primarykeyconstraint.h"
#include "foreignkeyconstraint.h"
#include "checkconstraint.h"

extern "C" {
	int yylex(void);
	int yyparse(void);
	void yyerror (char* c );
	 };

struct  ColumnOrConstraint{
	bool isConstraint;
	union {
		TableColumn * column;
		TableConstraint * constraint;
		};
	};

struct ColumnsAndConstraints {
	TableColumnList * columns;
	TableConstraintList* constraints;
};

struct ValueExpressionAndRename{
	Expression * expression;
	char * rename;
};

struct QueryAndRenames{
	SimpleQuery * sQuery;
	ColumnList * columnList;
};

struct QueryTreeAndRenames{
	QueryTree * queryTree;
	ColumnList * columnList;
};

struct NameAndColumns{
	char * name;
	ColumnList * columns;
};

extern Schema * schema;

enum signs {PLUSSIGN, MINUSSIGN};
enum com_op {GT_OP,LT_OP,EQ_OP,NEQ_OP, LEQ_OP, GEQ_OP};

%}
%token CREATE TABLE INT UNSIGNED_INT LP RP COMMA VIEW AS PERIOD CONSTRAINT UNIQUE PRIMARYKEY SELECT ASTERISK SOLIDUS PLUS MINUS WHERE GROUP BY HAVING IS_NOT IS NOT FROM NULLT DEFAULT TRUET FALSET UNKNOWN OR AND EQUALOP LTOP GTOP UNIQUE PRIMARY KEY FOREIGN REFERENCES CHECK E SC UNIONOP INTERSECTOP EXCEPT VALUES EXISTS BOOL_T BOOLEAN_T CHAR VARCHAR CHARACTER INTEGERT
%start start
%union
{
	char * string;
	Expression * expr;
	PrimaryExpression * primaryExpr;
	NumericExpression * numExpr;
	NumericPrimaryExpression * numPrimaryExpr;
	IntPrimaryExpression * intPrimaryExpr;
	ColumnReference * colRef;
	BooleanExpression * boolExpr;
	signs sign;
	com_op compOp;
	bool boolean;
	TruthValue * truthVal;
	TableColumn * ColDef;
	TableColumnType ColType;
	TableConstraint * TabConst;
	ColumnOrConstraint * ColumnOrConst;
	ColumnsAndConstraints * ColumnsAndConst;
	Table * Tab;
	View * ViewT;
	Schema * Sch;
	ColumnList * ColList;
	From * FromT;
	FromComponent * FromComp;
	Where * WhereT;
	ValueExpressionAndRename * ExprAndRename;
	std::vector<ValueExpressionAndRename *> * ExprAndRenameList;
	QueryTreeAndRenames * QueryTAndRenames;
	SimpleQuery * SQuery;
	QueryAndRenames * SQueryAndRenames;
	ExistsExpression * Exists;
	std::vector<ColumnReference*> * ColRefs;
	GroupBy * Gb;
	PrimaryKeyConstraint * PrimKeyConst;
	ForeignKeyConstraint * ForKeyConst;
	NameAndColumns * NameCols;

}

%token <string> IDENTIFIER UNSIGNED_INT
%type <string> identifier qualifier column_name unsigned_integer table_name as_clause correlation_name correlation_specification constraint_name_definition length
%type <expr> value_expression numeric_value_expression term factor value_expression_primary numeric_primary unsigned_literal unsigned_numeric_literal exact_numeric_literal row_value_constructor
%type <primaryExpr> unsigned_value_specification
%type <colRef> grouping_column_reference column_reference
%type <sign> sign
%type <numExpr>
%type <numPrimaryExpr>
%type <compOp> comp_op
%type <boolExpr> search_condition boolean_factor boolean_term boolean_test boolean_primary predicate comparison_predicate hc
%type <truthVal> truth_value
%type <ColDef> column_definition
%type <ColType> data_type numeric_type exact_numeric_type boolean_type character_string_type
%type <TabConst> table_constraint table_constraint_definition check_constraint_definition
%type <ColumnOrConst> table_element
%type <ColumnsAndConst> table_element_list
%type <Tab> table_definition
%type <Sch> start
%type <ColList> column_name_list view_column_list vcl unique_column_list reference_column_list
%type <FromT> from_clause table_reference_list
%type <FromComp> table_reference
%type <WhereT> wc
%type <ViewT> view_definition
%type <ExprAndRename> derived_column select_sublist
%type <ExprAndRenameList> select_list select_list2
%type <QueryTAndRenames> non_join_query_expression query_expression subquery
%type <SQueryAndRenames> simple_table query_term query_specification non_join_query_term
%type <Exists> exists_predicate
%type <ColRefs> grouping_column_reference_list
%type <Gb> gbc
%type <PrimKeyConst> unique_constraint_definition
%type <ForKeyConst> referential_constraint_definition
%type <NameCols> references_specification, referenced_table_and_columns

%%

start:
	/*empty*/
	table_definition {
		$$ = new Schema();
		Table * t = $1;
		$$->add(t);
		schema=$$;
		}

	|start SC table_definition{
		Table * t = $3;
		$1->add(t);
		$$=$1;
		schema = $$;
		}

	|view_definition
		{
		$$ = new Schema();
		View * v = $1;
		$$->add(v);
		schema=$$;
		}
		|start SC view_definition
		{
		View * v = $3;
		$1->add(v);
		$$=$1;
		schema = $$;
		}
	|start SC
	;

view_definition	: create_view table_name vcl AS query_expression //TODO[ WITH [ levels clause ] CHECK OPTION ]
		{
			ColumnList * cl;
			if ($3!=NULL) cl = $3;
			else cl=$5->columnList;
			//std::cout<<cl->toString();
			//std::cout<<$5->queryTree->toString();
			//std::cout<<$2;
			View * v = new View(cl,$5->queryTree,$2);
			$$=v;
		}
	;

create_view: CREATE VIEW
	;
vcl 	:/*empty*/{$$=NULL;}
	|LP view_column_list RP {$$=$2;}
	;

view_column_list	: column_name_list
			;

query_expression 	:	non_join_query_expression
			//TODO| joined_table
			;

non_join_query_expression :
	non_join_query_term
	{
		$$= new QueryTreeAndRenames();
		$$->queryTree = new QueryTree($1->sQuery);
		$$->columnList = $1->columnList;
	}
	|query_expression UNIONOP query_term
	{
		QueryTree * qt = new QueryTree($3->sQuery);
		$$= new QueryTreeAndRenames();
		$$->queryTree = new QueryTree(UNION,$1->queryTree,qt);
		$$->columnList = $1->columnList;
	}
	|query_expression INTERSECTOP query_term
	{
		QueryTree * qt = new QueryTree($3->sQuery);
		$$= new QueryTreeAndRenames();
		$$->queryTree =new QueryTree(INTERSECTION,$1->queryTree,qt);
		$$->columnList = $1->columnList;
	}
	//|	query expression UNION [ ALL ] [ corresponding spec ] query term
	//|	query expression EXCEPT [ ALL ] [ corresponding spec ] query term
	;

non_join_query_term :
		non_join_query_primary
	//TODO|	query term INTERSECT [ ALL ] [ corresponding spec ] query primary
	;

query_term :
	non_join_query_term
	//TODO |joined_table
	;

non_join_query_primary :
	simple_table
	| LP non_join_query_expression RP
	;

simple_table :
		query_specification
	|	table_value_constructor
	//TODO (it is not suported by mysql. Example: "create view v (a,b) as table t"	|explicit_table
	;

table_value_constructor: VALUES table_value_constructor_list
	;

table_value_constructor_list:
	row_value_constructor
	|table_value_constructor_list COMMA row_value_constructor
	;

query_specification:
	SELECT select_list from_clause wc gbc hc //meaning wc:[ <where clause> ], gbc:[ <group by clause> ] hc[ <having clause> ]
 	{
		Select * s = new Select();
		ColumnList * cl = new ColumnList();
		for (unsigned int i=0; i<$2->size(); i++){
			//check if it is a column referece
			ColumnReference * cr = dynamic_cast<ColumnReference*> ($2->at(i)->expression);
			if (cr!=NULL && cr->getTableId()=="*") {//if it is a colum reference that represents all the columns of all the tables in the from list
				vector<FromComponent*>* f = $3->getComponents();
				for (int j =0; j<f->size(); j++){
					SchemaComponent *schComp = NULL;
					schema->get(f->at(j)->getName(),schComp);
					std::vector<Column*> * schemaColumns = schComp->getColumns()->getColumns();
				  	for (int k=0; k<schemaColumns->size(); k++){
						Column * c = dynamic_cast<Column*> (schemaColumns->at(k));
						ColumnReference * colRef= new ColumnReference(f->at(j)->getRename(),c->getName());
						s->addExpression(colRef);
						cl->addColumn(c->getName());
					}
				}
			}
			else if (cr!=NULL && cr->getTableId()!="*" && cr->getColumnId()=="*") {//if it is a colum reference that represents all the columns of all the tables in the from list
			  vector<FromComponent*>* f = $3->getComponents();
					SchemaComponent *schComp = NULL;
					int j = 0;
					schema->get(cr->getTableId(),schComp);
                    if (schComp==NULL){
                        while ( (j< f->size()) && f->at(j)->getRename()!=cr->getTableId()){
                            j++;
                        }
					if (j<f->size()) schema->get(f->at(j)->getName(),schComp);
					}
					std::vector<Column*> * schemaColumns = schComp->getColumns()->getColumns();
					for (int k=0; k<schemaColumns->size(); k++){
						Column * c = dynamic_cast<Column*> (schemaColumns->at(k));
						ColumnReference * colRef= new ColumnReference(cr->getTableId(),c->getName());
						s->addExpression(colRef);
						cl->addColumn(c->getName());
					}

			}
			else if (cr!=NULL && cr->getTableId()=="" && cr->getColumnId()!=""){
				vector<FromComponent*>* f = $3->getComponents();
				bool found = false;
				int j=0;
				int k=0;
				while (j<f->size() && !found){
					SchemaComponent *schComp = NULL;
					schema->get(f->at(j)->getName(),schComp);
					std::vector<Column*> * schemaColumns = schComp->getColumns()->getColumns();
					while (k<schemaColumns->size()&&  !found){
						Column * c = dynamic_cast<Column*> (schemaColumns->at(k));
						if (c->getName()==cr->getColumnId()){
							found=true;
							ColumnReference * colRef= new ColumnReference(f->at(j)->getRename(),c->getName());
							s->addExpression(colRef);
							cl->addColumn(c->getName());
						}
					k++;
					}
				j++;
				}
			}
			else {
					s->addExpression($2->at(i)->expression);
					cl->addColumn($2->at(i)->expression->toString());
			}
		}
		$$ = new QueryAndRenames();
		//std::cout<<"!!!!!!!!!!!!!!!!!!!!!\n"<<$5->toString()<<"\n"<<$6->toString();
		$$->sQuery = new SimpleQuery(s,$3,$4,$5,$6);
		$$->columnList = cl;

	}
	//TODO |SELECT <set quantifier> select_list from_clause wc gbc hc //meaning wc:[ <where clause> ], gbc:[ <group by clause> ] hc[ <having clause> ]
	;

table_expression:
	from_clause wc gbc hc //meaning wc:[ <where clause> ], gbc:[ <group by clause> ] hc[ <having clause> ]
	;

from_clause :
	FROM table_reference_list
		{ $$=$2;
		}
	;

table_reference :
	table_name {
		FromComponent * fc = new FromComponent($1,$1);
		$$= fc;
		}
	|table_name correlation_specification {
		FromComponent * fc = new FromComponent($1,$2);
		$$= fc;
		}
	|table_name AS correlation_specification {
		FromComponent * fc = new FromComponent($1,$3);
		$$= fc;
		}
	//TODO|   <derived table> <correlation specification>
	//TODO|   <joined table>
	;

correlation_specification :
		 correlation_name {$$=$1;}
		//Not suported in mysql | correlation_name LP derived_column_list RP
		;

table_reference_list:
	table_reference
		{From * f = new From();
		f->addFromComponent($1);
		$$=f;
		}
	|table_reference_list COMMA table_reference
		{$1->addFromComponent($3);
		$$=$1;
		}
	;

wc:
	/*empty*/ 
	{ $$=NULL; }
	| WHERE search_condition
	{
		Where* w = new Where();
		w->setExpression($2);
		$$=w;
	}
	;

gbc:
	//empty
	{$$=NULL;}
	|GROUP BY grouping_column_reference_list {$$= new GroupBy($3);}
	;

hc:
	//empty
	{$$=NULL;}
    |HAVING search_condition {$$=$2;}
	;

grouping_column_reference_list :
	grouping_column_reference
		{$$=new std::vector<ColumnReference*>();
		$$->push_back($1);}
	|grouping_column_reference  COMMA grouping_column_reference_list
		{$$->push_back($1);}
	;

grouping_column_reference :
	column_reference {$$=$1;}
	//NOT IMPLEMENTED|<column reference> [ <collate clause> ]
	;

select_list :
	ASTERISK{
		ColumnReference * cr = new ColumnReference("*","*");
		ValueExpressionAndRename * v=new ValueExpressionAndRename();
		v->expression=cr;
		v->rename="";
		$$= new std::vector<ValueExpressionAndRename*>();
		$$->push_back(v);
		}

	|select_list2
	;

select_list2:
	select_sublist	{
		$$= new std::vector<ValueExpressionAndRename*>();
		$$->push_back($1);
	}
	|select_list2 COMMA select_sublist {
		$1->push_back($3);
		$$=$1;
	}
	;

select_sublist :
	derived_column
	| qualifier PERIOD ASTERISK
		{
			ColumnReference * cr = new ColumnReference($1,"*");
			$$=new ValueExpressionAndRename();
			$$->expression = cr;
			$$->rename="";
		}
	;

derived_column :
	value_expression
		{
		$$ = new ValueExpressionAndRename();
		$$->expression=$1;
		$$->rename="";
		}
	|value_expression as_clause
		{
		$$ = new ValueExpressionAndRename();
	        $$->expression=$1;
		$$->rename=$2;
		}
	;

as_clause :
	column_name {$$=$1;}
	|AS column_name {$$=$2;}
	;

value_expression:
	numeric_value_expression
	//TODO|   <string value expression>
	//TODO|   <datetime value expression>
	//TODO|   <interval value expression>
	;

numeric_value_expression :
		term{$$=$1;}
	|   numeric_value_expression PLUS term{
		$$= new NumericBinaryOperation($1,"+",$3);
		}
	|   numeric_value_expression MINUS term{
		$$= new NumericBinaryOperation($1,"-",$3);
		}
	;

term :
		factor {$$=$1;}
	|   term ASTERISK factor{
		$$= new NumericBinaryOperation($1,"*",$3);
		}
	|   term SOLIDUS factor{
		$$= new NumericBinaryOperation($1,"/",$3);
		}
	;

factor :
	numeric_primary {$$=$1}
	|sign numeric_primary
	{
		if ($1==MINUSSIGN){
		std::string s ("-");
		NumericUnaryOperation * n = new NumericUnaryOperation($2, s.c_str());
		$$= n;
		}
	}
	;

sign :
	PLUS {$$=PLUSSIGN}
	|MINUS {$$=MINUSSIGN}
	;

numeric_primary :
	value_expression_primary {$$=$1;}
	//TODO| numeric_value_function
	;
unsigned_value_specification :
	unsigned_literal
	//TODO| <general value specification>
	;

unsigned_literal:
	unsigned_numeric_literal
	//| <general literal>
	;

unsigned_numeric_literal :
		exact_numeric_literal {$$=$1;}
	//TODO |	approximate_numeric_literal {$$=$1;}
	;
exact_numeric_literal :
	/* FUTURE WORK: float type
	unsigned_integer PERIOD
	| unsigned_integer PERIOD unsigned_integer
	| PERIOD unsigned_integer
	|*/ unsigned_integer
		{
			int i = atoi($1);
			$$= new IntPrimaryExpression(i);
		}
	;

unsigned_integer :
	UNSIGNED_INT
	;
/*
approximate_numeric_literal :
	mantissa E exponent
	;
mantissa : exact_numeric_literal;

exponent : signed_integer;

signed_integer :
	unsigned_integer
	|sign unsigned_integer
	;
*/

value_expression_primary :
	unsigned_value_specification {$$=$1;}
	| column_reference {$$=$1;}
	//TODO|   <set function specification>
	//TODO|   <scalar subquery>
	//TODO|   <case expression>
	| LP value_expression RP {
			$$=$2;
		}
	//TODO|   <cast specification>
	;

column_reference :
	qualifier PERIOD column_name
		{
			ColumnReference * cr= new ColumnReference($1,$3);
			$$=cr;
		}
	|column_name
		{
			ColumnReference * cr = new ColumnReference("",$1);
			$$=cr;
		}
	;

qualifier :
	table_name
	//correlation_name
	;


table_name 	: identifier
		;

column_name 	: identifier
		;

correlation_name : identifier
		;

search_condition:
	boolean_term
	|search_condition OR boolean_term {
		$$= new LogicBinaryOperation($1,"or",$3);
		}
	;

boolean_term :
	boolean_factor
	|boolean_term AND boolean_factor{
		$$= new LogicBinaryOperation($1,"and",$3);
	}
	;

boolean_factor :
	NOT boolean_test{
			$$=new LogicUnaryOperation("not",$2);
	}
	|boolean_test {$$=$1;}	
	;

boolean_test :
	boolean_primary
	//TODO?|boolean_primary IS truth_value
	//TODO?|boolean_primary IS_NOT truth_value
	;

boolean_primary :
	predicate {$$=$1;}
	| LP search_condition RP {$$=$2;}
	;

predicate :
	comparison_predicate
	//TODO|   <between predicate>
	//TODO|   <in predicate>
	//TODO|   <like predicate>
	//TODO|   <null predicate>
	//TODO|   <quantified comparison predicate>
       |   exists_predicate
	//TODO|   <match predicate>
	//TODO|   <overlaps predicate>
	;

truth_value:
	TRUET {$$=new TruthValue(True);}
	|FALSET {$$=new TruthValue(False);}
	|UNKNOWN {$$=new TruthValue(Unknown);}
	;

comparison_predicate:
	 row_value_constructor comp_op row_value_constructor
		{
		switch ($2){
			case GT_OP:
				$$= new LogicBinaryOperation($1,">",$3);
				break;
			case EQ_OP:
				$$= new LogicBinaryOperation($1,"==",$3);
				break;
			case LT_OP:
				$$= new LogicBinaryOperation($1,"<",$3);
				break;
			case NEQ_OP:
				$$= new LogicBinaryOperation($1,"!=",$3);
				break;
			case LEQ_OP:
				$$= new LogicBinaryOperation($1,"<=",$3);
				break;
			case GEQ_OP:
				$$= new LogicBinaryOperation($1,">=",$3);
				break;
			}
		}
	;

comp_op:
	EQUALOP {$$=EQ_OP;}
	|   LTOP GTOP {$$= NEQ_OP;}// meaning not equals operator <>
	|   LTOP{$$=LT_OP;}
	|   GTOP{$$=GT_OP;}
	|   LTOP EQUALOP{$$=LEQ_OP}
	|   GTOP EQUALOP{$$=GEQ_OP}
	;

row_value_constructor :
	row_value_constructor_element
//TODO	|LP row_value_constructor_list RP
//TODO uncoment	|row_subquery
	;

row_value_constructor_element :
	value_expression
	|   NULLT // meaning null_specification
	|   DEFAULT // meaning default_specification
	;

/*
row_value_constructor_list:
	row_value_constructor_element
	|row_value_constructor_element COMMA row_value_constructor_list
	;
*/

exists_predicate : EXISTS subquery {
	$$=new ExistsExpression($2->queryTree);};

subquery :LP query_expression RP{$$=$2;};


table_definition	:
	create_table glt table_name LP table_element_list RP on_comit
		{
			$$ = new Table($5->columns, $5->constraints, $3);
		}
	;

create_table 	: CREATE TABLE
		;

identifier	: /*TODO [ introducercharacter set specification ]*/ actual_identifier
		;

actual_identifier: IDENTIFIER
	/*in the grammar we are based on it's defined as like:
	 regular_identifier
	| delimited_identifier */
	;

table_element_list	:
	table_element
		{
			$$= new ColumnsAndConstraints();
			$$->columns = new TableColumnList();
			$$->constraints = new TableConstraintList();
			if ($1->isConstraint) $$->constraints->addTableConstraint($1->constraint);
			else $$->columns->addColumn($1->column);
		}
	| table_element_list COMMA table_element
		{
			if ($3->isConstraint) {
				$$->constraints->addTableConstraint($3->constraint);
			}
			else $$->columns->addColumn($3->column);
		}
	;
table_element	:	column_definition
			{
				$$ = new ColumnOrConstraint();
				$$->isConstraint=false;
				$$->column= $1;
			}
		| table_constraint_definition
		{
			$$ = new ColumnOrConstraint();
			$$->isConstraint=true;
			$$->constraint=$1;
		}
		;

table_constraint_definition :
	table_constraint {$$=$1;} // [ constraint check time ] 
	| constraint_name_definition table_constraint {$$= $2;} // We do not care about it's name [constraint check time]
	;

table_constraint :
	unique_constraint_definition
	|referential_constraint_definition
	|check_constraint_definition
	;
	
referential_constraint_definition :
		FOREIGN KEY LP reference_column_list RP references_specification {$$=new ForeignKeyConstraint($4,$6->columns, $6->name);}
		;

reference_column_list: column_name_list{$$=$1;};

references_specification:
	REFERENCES referenced_table_and_columns {$$=$2;}
	//TODO REFERENCES <referenced table and columns> [ MATCH <match type> ] [ <referential triggered action> ]
	;

referenced_table_and_columns : 
	table_name	{$$= new NameAndColumns();$$->name=$1;}
	|table_name LP reference_column_list RP {$$= new NameAndColumns();$$->name=$1; $$->columns=$3;}
;
unique_constraint_definition:
	unique_specification LP unique_column_list RP
		{$$=new PrimaryKeyConstraint($3);
		}
	;

unique_specification : UNIQUE // {$$=UN}
	| PRIMARY KEY // {$$=PK}
	;

unique_column_list : 
	column_name_list {$$=$1;}
	;

column_name_list:
	 column_name
		{ColumnList * cl = new ColumnList();
		cl->addColumn($1);
		$$=cl;
		}
	| column_name_list COMMA column_name
		{
		$1->addColumn($3);
		$$=$1;
		}
	;

constraint_name_definition:
	CONSTRAINT identifier {$$=$2}
	;

check_constraint_definition:
CHECK LP search_condition RP {$$ = new CheckConstraint($3);}
	;

constraint_name	:
	qualified_name
	;

qualified_name :
	 qualified_identifier
	//| schema_name PERIOD qualified_identifier
	;

qualified_identifier :
	identifier
	;

schema_name :
	catalog_name PERIOD unqualified_schema_name
	|unqualified_schema_name
	;

catalog_name : identifier
	;

unqualified_schema_name : identifier
	;


column_definition	: column_name data_type //TODO default_clause column_constraint_definition_list  collate_clause
				{
					$$ = new TableColumn($2,$1);
				}
			//TODO |column_name domain_name default_clause column_constraint_definition_list collate_clause
			;

data_type	:
character_string_type
	//TODO	character_string_type CHARACTER SET character_set_specification
	//TODO|	national character string type
	//TODO|	bit string type
	|	numeric_type
	//TODO|	datetime type
	//TODO|	interval type
	|boolean_type
		;

numeric_type	:
		exact_numeric_type
	//TODO|	approximate numeric type
		;
exact_numeric_type	:
	//TODO 	NUMERIC [ left paren precision [ comma scale ] right paren ]
	//TODO| 	DECIMAL [ left paren precision [ comma scale ] right paren ]
	//TODO| 	DEC [ left paren precision [ comma scale ] right paren ]
	INTEGERT {
			TableColumnType tc;
			tc.type = INTEGER;
			tc.size = 0;
			$$=tc;
		}
	|	INT {
			TableColumnType tc;
			tc.type = INTEGER;
			tc.size = 0;
			$$=tc;
		}
	//TODO|	SMALLINT

character_string_type :
		CHARACTER LP length RP{
			TableColumnType tc;
			tc.type = STRING;
			tc.size = atoi($3);
			$$=tc;		
		}
	|	CHAR LP length RP{
			TableColumnType tc;
			tc.type = STRING;
			tc.size = atoi($3);
			$$=tc;		
		}
	//|	CHARACTER VARYING [ <left paren> <length> <right paren> ]
	//|	CHAR VARYING [ <left paren> <length> <right paren> ]
	|	VARCHAR LP length RP{
			TableColumnType tc;
			tc.type = STRING;
			tc.size = atoi($3);
			$$=tc;		
		}
	;

length : unsigned_integer{$$=$1};

boolean_type :
BOOL_T {TableColumnType tc;
  tc.type= BOOLEAN;
  $$=tc;  
 }
|BOOLEAN_T {TableColumnType tc;
  tc.type = BOOLEAN;
  $$=tc;  
 }
	;
//TODO translate:

//[ { GLOBAL | LOCAL } TEMPORARY ]
glt	:
	;
//[ ON COMMIT { DELETE | PRESERVE } ROWS ]
on_comit:
	;
//domain name
domain_name	:
		;

%%
#ifndef PARSER
#define PARSER

#define YYERROR_VERBOSE=1

Schema * schema;

void yyerror(char* s)
{
  fprintf (stderr,"%s\nERROR: Error parsing SQL code. If you are sure the SQL code you have introduced is correct and you think stcg must support it, please post a new Issue in stcg development repository: http://code.google.com/p/stcg/issues/list.\n", s);
 exit(EXIT_FAILURE);
}

Schema * generateSchema(){
	extern int yydebug;	
	#ifdef YYDEBUG
		yydebug=1;
	#endif 

  yyparse();
  return schema;
}



/*

main(int argc, char* argv[]){
	extern int yydebug;
	yyparse();
	std::cout<<schema->toString();

	FormulaGenerator * generator = new FormulaGenerator(schema);

	std::string name;
	std::cout << "Please, write the name of the table you want to generate it's formula:\n";
	std::cin >> name;

    SchemaComponentFormula * formula = NULL;
    if(generator->generateFormulaFor(name,formula)){
        std::cout << formula->toString();
    }
}

*/
#endif

